package com.cskaoyan.javase._2inner._3local._3notice;

/**
 * 局部内部类的注意事项:
 * 在局部内部类的成员方法中，如果想要访问作用域内部的局部变量，那么该变量：
 *      1.要么直接就用final修饰，是一个局部常量。(不能修改它的值)
 *      2.要么就是一个事实上的常量，即只能赋值一次，相当于用final修饰它。
 * 总之,在局部内部类当中被访问的作用域内部的局部变量,应该是一个常量.
 * 为什么?
 * 主要原因:
 * 局部变量和对象的生命周期的冲突
 * 局部变量随着方法出栈被销毁,但对象仍然存在,该对象的成员方法依然会访问局部变量
 * 为了解决这种生命周期的冲突
 * JVM会在创建 访问了作用域局部变量的 局部内部类对象时
 * 将该局部变量作为局部内部类对象的成员变量
 * 在很多时候,在解决问题的时候,解决问题所使用的方案,它可能本身就是一个问题
 * 一旦用拷贝成员变量的方式解决生命周期的冲突
 * 那就存在成员变量和局部变量取值同步的问题
 * 为了避免这个同步的麻烦,java的设计者干脆禁止修改,使它成为一个常量.
 *
 * 扩展:
 * 在java7及以前的JDK版本中,在局部内部类中,被访问的作用域内部的局部变量,必须显式声明为final局部常量
 * 但是到了Java8,就无须这么做了,只需要不修改它(将它作为一个真正意义上的常量)即可
 * 这是一种语法糖,实现原理不变了,底层多做事.
 *
 * 马上要学习的匿名内部类,Lambda表达式都是特殊的,简化的局部内部类
 * 它们也都具有这个特点.
 *
 * @since 10:57
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
}

class EnclosedClazz {
    public void test() {
        // 方法的局部变量a
        int a = 10;
        class Inner {
            public void testInner() {
                System.out.println(a);
                // Variable 'a' is accessed from within inner class, needs to be final or effectively final
                // System.out.println(a++);
            }
        }
    }
}